﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GraphMLComplexType;
using QuickGraph;
using QuickGraph.Algorithms.ShortestPath;

namespace ComplexNetCentralityLib
{
    public class ConnectionEfficiency
    {

        public static double globalConnectionEfficiency(AdjacencyGraph<IGraphMLComplexType, EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>> socialNetwork)
        {
            double sum = 0.0;
            var fw = new FloydWarshallAllShortestPathAlgorithm<IGraphMLComplexType, EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>>(socialNetwork, ComplexNetCentrality.weights);
            fw.Compute();
            foreach (var i in socialNetwork.Vertices)
            {
                foreach (var j in socialNetwork.Vertices)
                {
                    if (!i.Equals(j))
                    {
                        int dij = 0;
                        IEnumerable<EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>> path;
                        if (fw.TryGetPath(i, j, out path))
                        {
                            foreach (var edge in path) dij++;
                            sum += 1 / (double)dij;
                        }
                    }
                }
            }
            return 2 * sum / (socialNetwork.VertexCount * (socialNetwork.VertexCount - 1));
        }

        private static IGraphMLComplexType randomNaighbour(AdjacencyGraph<IGraphMLComplexType, EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>> socialNetwork, IGraphMLComplexType node)
        {
            List<IGraphMLComplexType> nodeList = new List<IGraphMLComplexType>();
            foreach (var e in socialNetwork.Edges)
            {
                if (e.Source.Equals(node))
                {
                    if (!nodeList.Contains(e.Target))
                    {
                        nodeList.Add(e.Target);
                    }
                }
                if (e.Target.Equals(node))
                {
                    if (!nodeList.Contains(e.Source))
                    {
                        nodeList.Add(e.Source);
                    }
                }
            }
            var nodeArray = nodeList.ToArray();
            if (nodeArray.Length == 0)
            {
                return node;
            }
            Random random = new Random();
            return nodeArray[random.Next(nodeArray.Length)];
        }

        public static double vaccinateNaighbour(AdjacencyGraph<IGraphMLComplexType, EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>> socialNetwork, int imun_n)
        {
            var nodes = socialNetwork.Vertices.ToArray<IGraphMLComplexType>();
            Random random = new Random();
            for (int i = 1; (i < imun_n && i < nodes.Length); i++)
            {
                int r = random.Next(nodes.Length - i + 1);
                socialNetwork.RemoveVertex(randomNaighbour(socialNetwork,nodes[r]));
                nodes[r] = nodes[nodes.Length - i];
            }
            return globalConnectionEfficiency(socialNetwork);
        }

        public static double vaccinateRandom(AdjacencyGraph<IGraphMLComplexType, EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>> socialNetwork, int imun_n)
        {
            IGraphMLComplexType[] nodes = new IGraphMLComplexType[socialNetwork.VertexCount];
            nodes = socialNetwork.Vertices.ToArray<IGraphMLComplexType>();
            Random random = new Random();
            for (int i = 1; (i < imun_n && i < nodes.Length); i++)
            {
                int r = random.Next(nodes.Length - i + 1);
                socialNetwork.RemoveVertex(nodes[r]);
                nodes[r] = nodes[nodes.Length - i];
            }
            return globalConnectionEfficiency(socialNetwork);
        }

        public static double vaccinateByBetweennessCentrality(AdjacencyGraph<IGraphMLComplexType, EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>> socialNetwork, int imun_n)
        {
            IGraphMLComplexType max;
            double maxImportance, vImportance;
            ComplexNetCentrality.betweennessCentralityImportance(socialNetwork);
            for (int i = 1; i < imun_n; i++)
            {
                max = socialNetwork.Vertices.First<IGraphMLComplexType>();
                double.TryParse(max.Keys["importance"], out maxImportance);
                foreach (var v in socialNetwork.Vertices)
                {
                    double.TryParse(v.Keys["importance"], out vImportance);
                    if (vImportance > maxImportance)
                    {
                        max = v;
                        maxImportance = vImportance;
                    }
                }
                socialNetwork.RemoveVertex(max);
            }
            return globalConnectionEfficiency(socialNetwork);
        }

        public static double vaccinateByDegreeCentrality(AdjacencyGraph<IGraphMLComplexType, EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>> socialNetwork, int imun_n)
        {
            IGraphMLComplexType max;
            double maxImportance, vImportance;
            ComplexNetCentrality.degreeCentralityImportance(socialNetwork);
            for (int i = 1; i < imun_n; i++)
            {
                max = socialNetwork.Vertices.First<IGraphMLComplexType>();
                double.TryParse(max.Keys["importance"],out maxImportance);
                foreach (var v in socialNetwork.Vertices)
                {
                    double.TryParse(v.Keys["importance"],out vImportance);
                    if (vImportance > maxImportance)
                    {
                        max = v;
                        maxImportance = vImportance;
                    }
                }
                socialNetwork.RemoveVertex(max);
            }
            return globalConnectionEfficiency(socialNetwork);
        }

        public static double vaccinateByClosenessCentrality(AdjacencyGraph<IGraphMLComplexType, EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>> socialNetwork, int imun_n)
        {
            IGraphMLComplexType max;
            double maxImportance, vImportance;
            ComplexNetCentrality.closenessCentralityImportance(socialNetwork);
            for (int i = 1; i < imun_n; i++)
            {
                max = socialNetwork.Vertices.First<IGraphMLComplexType>();
                double.TryParse(max.Keys["importance"], out maxImportance);
                foreach (var v in socialNetwork.Vertices)
                {
                    double.TryParse(v.Keys["importance"], out vImportance);
                    if (vImportance > maxImportance)
                    {
                        max = v;
                        maxImportance = vImportance;
                    }
                }
                socialNetwork.RemoveVertex(max);
            }
            return globalConnectionEfficiency(socialNetwork);
        }

        public static double vaccinateByRadiusCentrality(AdjacencyGraph<IGraphMLComplexType, EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>> socialNetwork, int imun_n)
        {
            IGraphMLComplexType max;
            double maxImportance, vImportance;
            ComplexNetCentrality.radiusCentralityImportance(socialNetwork);
            for (int i = 1; i < imun_n; i++)
            {
                max = socialNetwork.Vertices.First<IGraphMLComplexType>();
                double.TryParse(max.Keys["importance"], out maxImportance);
                foreach (var v in socialNetwork.Vertices)
                {
                    double.TryParse(v.Keys["importance"], out vImportance);
                    if (vImportance > maxImportance)
                    {
                        max = v;
                        maxImportance = vImportance;
                    }
                }
                socialNetwork.RemoveVertex(max);
            }
            return globalConnectionEfficiency(socialNetwork);
        }

    }
}
